﻿using System;
using Amazon.S3.Model;

namespace Lucene.Net.Store.S3 {

	public class IndexInput : Lucene.Net.Store.IndexInput {
		private Directory s3Directory;
		private Lucene.Net.Store.IndexInput indexInput;
		private Lucene.Net.Store.Directory cacheDirectory;
		private readonly String name;

		public IndexInput(Directory s3Directory, String name) {
			this.s3Directory = s3Directory;
			this.name = name;
			this.cacheDirectory = s3Directory.CacheDirectory;

			Boolean fileNeeded = false;
			if (!this.cacheDirectory.FileExists(name)) {
				fileNeeded = true;
			}
			else {
				Int64 cachedFileLength = this.cacheDirectory.FileLength(name);
				Int64 cloudFileLength = this.s3Directory.FileLength(name);
				if (cachedFileLength != cloudFileLength) {
					fileNeeded = true;
				}
				else {
					DateTime cachedFileLastModified = new DateTime(this.cacheDirectory.FileModified(name), DateTimeKind.Local).ToUniversalTime();
					DateTime cloudFileLastModified = new DateTime(this.s3Directory.FileModified(name), DateTimeKind.Utc);
					if (cachedFileLastModified != cloudFileLastModified) {
						fileNeeded = true;
					}
				}
			}

			if (fileNeeded) {
				StreamOutput fileStream = this.s3Directory.CreateCachedOutputAsStream(name);
				this.s3Directory.ReadFile(name, fileStream);

				fileStream.Flush();
				fileStream.Close();

				// Let's open the data as an input index!
				this.indexInput = this.cacheDirectory.OpenInput(name);
			}
			else {
				// Let's open the data as an input index!
				this.indexInput = this.cacheDirectory.OpenInput(name);
			}
		}

		public override void Close() {
			this.indexInput.Close();
			this.indexInput = null;
			this.s3Directory = null;
		}

		public override Int64 GetFilePointer() {
			return this.indexInput.GetFilePointer();
		}

		public override Int64 Length() {
			return this.indexInput.Length();
		}

		public override Byte ReadByte() {
			return this.indexInput.ReadByte();
		}

		public override void ReadBytes(Byte[] b, Int32 offset, Int32 len) {
			this.indexInput.ReadBytes(b, offset, len);
		}

		public override void Seek(Int64 pos) {
			this.indexInput.Seek(pos);
		}
	}
}